package com.yichat.micro.msghttpservice.core.record.service;

import com.yichat.micro.msghttpservice.common.Constants;
import com.yichat.micro.msghttpservice.common.result.HttpResult;
import com.yichat.micro.msghttpservice.common.util.JsonUtil;
import com.yichat.micro.msghttpservice.core.record.batch.MultiChildRecordBatch;
import com.yichat.micro.msghttpservice.core.record.batch.RecordBatch;
import com.yichat.micro.msghttpservice.core.record.mapper.MultiChildRecordMapper;
import com.yichat.micro.msghttpservice.core.record.mapper.RecordMapper;
import com.yichat.micro.msghttpservice.core.record.model.MultiChildRecord;
import com.yichat.micro.msghttpservice.core.record.model.Record;
import com.yichat.micro.msghttpservice.core.retry.RetryMsgHttpRequestVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * Created by chenmohan on 2019/04/16
 *
 * @description
 */
@Slf4j
@Service
public class RecordServiceImpl implements RecordService {

    @Autowired
    RecordMapper recordMapper;

    @Autowired
    MultiChildRecordMapper multiChildRecordMapper;

    @Autowired
    RecordBatch recordBatcher;

    @Autowired
    MultiChildRecordBatch multiChildRecordBatcher;

    @Override
    public void record(RetryMsgHttpRequestVo retryVo, HttpResult httpResult) {

    }

    /**
     * 在请求发送前向日志中插入没有响应结果的请求日志
     *
     * @param retryVo
     */
    @Override
    public void recordBeforeResponse(RetryMsgHttpRequestVo retryVo) {
        HttpResult httpResult = new HttpResult();
        httpResult.setCode(Constants.disable);
        httpResult.setData(Constants.empty_string);
        //如果是批量请求,新增1条没有结果的MultiChildRecord
        if (retryVo.isBatch()) {
            MultiChildRecord childInsert = buildMultiRecord(retryVo, httpResult);
            multiChildRecordBatcher.insert(childInsert);
        }
        // 1.是一条单条请求 2.是批量请求并且还是第一条子请求
        // 2者满足其一则新增1条没有结果的Record
        if (!retryVo.isBatch() || (retryVo.isBatch() && retryVo.getCurrentListIndex() == 0)) {
            Record insert = buildRecord(retryVo, httpResult);
            recordBatcher.insert(insert);
        }
    }

    /**
     * 响应结果成功时候更新之前率先插入的请求日志结果
     *
     * @param retryVo
     * @param httpResult
     */
    @Override
    public void recordWithSuccessed(RetryMsgHttpRequestVo retryVo, HttpResult httpResult) {
        //响应码为200时,记录请求成功
        if (Constants.status_ok == httpResult.getCode()) {
            if (retryVo.isBatch()) {
                MultiChildRecord update = buildUpdateMultiRecord(retryVo, httpResult);
                multiChildRecordBatcher.update(update);
            } else {
                Record update = buildUpdateRecord(retryVo, httpResult);
                recordBatcher.update(update);
            }

        }
    }

    /**
     * 重试失败时候更新之前率先插入的请求日志结果
     *
     * @param retryVo
     */
    @Override
    public void recordWithRetryFailed(RetryMsgHttpRequestVo retryVo) {
        HttpResult retryFailedResult = new HttpResult();
        retryFailedResult.setCode(Constants.status_retry_failed);
        retryFailedResult.setData(Constants.msg_status_retry_failed);
        if (retryVo.isBatch()) {
            MultiChildRecord update = buildUpdateMultiRecord(retryVo, retryFailedResult);
            multiChildRecordBatcher.update(update);
        } else {
            Record update = buildUpdateRecord(retryVo, retryFailedResult);
            recordBatcher.update(update);

        }

    }

    /**
     * 批量请求最后一个也成功时,插入最后的子请求日志和更新总请求日志
     *
     * @param retryVo
     */
    @Override
    public void recoredWithBatchFailed(RetryMsgHttpRequestVo retryVo) {
        HttpResult batchFailedResult = new HttpResult();
        batchFailedResult.setCode(Constants.status_retry_failed);
        batchFailedResult.setData(Constants.msg_status_retry_failed);
        updateRecordWithBatch(retryVo, batchFailedResult);
    }

    /**
     * 批量请求最后一个也成功时,插入最后的子请求日志和更新总请求日志
     *
     * @param retryVo
     */
    @Override
    public void recoredWithBatchSuccessed(RetryMsgHttpRequestVo retryVo) {
        HttpResult successHttpResult = new HttpResult();
        successHttpResult.setCode(Constants.status_ok);
        successHttpResult.setData(Constants.empty_string);
        MultiChildRecord childInsert = buildMultiRecord(retryVo, successHttpResult);
        multiChildRecordBatcher.insert(childInsert);
        updateRecordWithBatch(retryVo, successHttpResult);
    }

    protected void doBathcRecordBeforeResponse(RetryMsgHttpRequestVo retryVo, HttpResult httpResult) {
        Record insert = buildRecord(retryVo, httpResult);
        recordMapper.insertSelective(insert);
    }

    /*
    protected void doRecord(RetryMsgHttpRequestVo retryVo, HttpResult httpResult) {
        //检查是否有存在日志记录(异步请求会率先生成id并插入到表中)
        Date now = new Date();
        if (retryVo.isBatch()) {
            MultiChildRecordExample example = new MultiChildRecordExample();
            example.createCriteria().andRecordIdEqualTo(retryVo.getSid()).andCurrentIndexEqualTo(retryVo.getCurrentListIndex());
            List<MultiChildRecord> multiChildRecords = null;
            try {
                multiChildRecords = multiChildRecordMapper.selectByExample(example);
            } catch (Exception e) {
                e.printStackTrace();
            }
            MultiChildRecord record = null;
            if (multiChildRecords != null && multiChildRecords.size() > 0) {
                record = multiChildRecords.get(0);
            }
            if (record != null) { //说明已经入库,更新数据
                MultiChildRecord update = buildUpdateMultiRecord(retryVo, httpResult);
                multiChildRecordMapper.updateByExampleSelective(update, example);
            } else {  //新增数据
                MultiChildRecord insert = buildMultiRecord(retryVo, httpResult);
                multiChildRecordMapper.insertSelective(insert);
            }
        } else {
            //Record record = recordMapper.selectByPrimaryKey(retryVo.getSid());
         //   if (record != null) {
                Record update = buildUpdateRecord(retryVo,httpResult);
                recordMapper.updateByPrimaryKeySelective(update);
            } else {
                Record insert = buildRecord(retryVo, httpResult);
                recordMapper.insertSelective(insert);
            }
        }
    }
    */

    protected void updateRecordWithBatch(RetryMsgHttpRequestVo retryVo, HttpResult httpResult) {
        Record update = buildUpdateRecord(retryVo, httpResult);
        recordBatcher.update(update);
    }

    /**
     * 构建单条请求的【新增】日志对象
     *
     * @param retryVo
     * @param httpResult
     * @return
     */
    protected Record buildRecord(RetryMsgHttpRequestVo retryVo, HttpResult httpResult) {
        //   RetryMsgHttpRequestVo retryVo0 = new RetryMsgHttpRequestVo();
        //    BeanUtils.copyProperties(retryVo, retryVo0);
        Date now = new Date();
        return Record.builder().id(retryVo.getSid())
                .parameter(JsonUtil.toJSON(retryVo))    //整个请求参数都要记录下来
                .sendResult(httpResult.getData())
                .sendStatus(httpResult.getCode())
                .requestDatetime(retryVo.getRequestDatetime())
                .createDatetime(now)
                .modifyDatetime(now)
                .build();
    }

    /**
     * 构建单条请求的【更新】日志对象
     *
     * @param retryVo
     * @param httpResult
     * @return
     */
    protected Record buildUpdateRecord(RetryMsgHttpRequestVo retryVo, HttpResult httpResult) {
        return Record.builder().id(retryVo.getSid())
                .sendResult(httpResult.getData())
                .sendStatus(httpResult.getCode())
                .modifyDatetime(new Date()).build();
    }


    /**
     * 构建批量请求中单条请求的【新增】日志对象
     *
     * @param retryVo
     * @param httpResult
     * @return
     */
    protected MultiChildRecord buildMultiRecord(RetryMsgHttpRequestVo retryVo, HttpResult httpResult) {
        //    RetryMsgHttpRequestVo retryVo0 = new RetryMsgHttpRequestVo();
        //   BeanUtils.copyProperties(retryVo, retryVo0);
        Date now = new Date();
        return MultiChildRecord.builder().recordId(retryVo.getSid())
                .parameter(JsonUtil.toJSON(retryVo))    //整个请求参数都要记录下来
                .sendResult(httpResult.getData())
                .sendStatus(httpResult.getCode())
                .currentIndex(retryVo.getCurrentListIndex())
                .requestDatetime(retryVo.getRequestDatetime())
                .createDatetime(now)
                .modifyDatetime(now)
                .build();
    }

    /**
     * 构建批量请求中单条请求的【更新】日志对象
     *
     * @param retryVo
     * @param httpResult
     * @return
     */
    protected MultiChildRecord buildUpdateMultiRecord(RetryMsgHttpRequestVo retryVo, HttpResult httpResult) {
        return MultiChildRecord.builder().recordId(retryVo.getSid())
                .sendResult(httpResult.getData())
                .sendStatus(httpResult.getCode())
                .currentIndex(retryVo.getCurrentListIndex())
                .modifyDatetime(new Date()).build();
    }

}
